AIDL Hal 开发指南8 —— 添加硬件访问服务

4/16/2024

# 定义 AIDL

创建 aidl 文件 frameworks/base/core/java/android/hardware/hello/IHelloHalManager.aidl

package android.hardware.hello;

/**
 * {@hide}
 */
interface IHelloHalManager {
    void hellohal_write(String str);
    String hellohal_read();
}
1
2
3
4
5
6
7
8
9

下面的 Android.bp 已经包含了该目录下几乎所有 aidl 文件和 java 文件的编译,所以我们不需要再将自定义的 IHelloHalManager.aidl 添加到编译环境

// frameworks/base/core/java/Android.bp
filegroup {
    name: "framework-core-sources",
    srcs: [                                                                                                                                                                                                            
        "**/*.java",
        "**/*.aidl",
    ],  
    exclude_srcs: [
        // Remove election toolbar code from build time
        "android/service/selectiontoolbar/*.aidl",
        "android/service/selectiontoolbar/*.java",
        "android/view/selectiontoolbar/*.aidl",
        "android/view/selectiontoolbar/*.java",
        "com/android/internal/widget/floatingtoolbar/RemoteFloatingToolbarPopup.java",
    ],
    visibility: ["//frameworks/base"],
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

接着编译:

source build/envsetup.sh
lunch aosp_cf_x86_64_phone-eng
make update-api
make framework-minus-apex -j32
1
2
3
4

然后再 out 目录下搜索:

cd out
find . -name "IHelloManager*"
./soong/.intermediates/frameworks/base/framework-minus-apex/android_common/gen/aidl/frameworks/base/core/java/android/hardware/hello/IHelloManager.aidl.d
./soong/.intermediates/frameworks/base/framework-minus-apex/android_common/javac/shard38/classes/android/hardware/hello/IHelloManager.class
./soong/.intermediates/frameworks/base/framework-minus-apex/android_common/javac/shard38/classes/android/hardware/hello/IHelloManager$Stub$Proxy.class
./soong/.intermediates/frameworks/base/framework-minus-apex/android_common/javac/shard38/classes/android/hardware/hello/IHelloManager$Stub.class
./soong/.intermediates/frameworks/base/framework-minus-apex/android_common/javac/shard38/classes/android/hardware/hello/IHelloManager$Default.class
./soong/.intermediates/frameworks/base/api/system-api-stubs-docs-non-updatable/android_common/gen/aidl/frameworks/base/core/java/android/hardware/hello/IHelloManager.aidl.d
./soong/.intermediates/frameworks/base/api/test-api-stubs-docs-non-updatable/android_common/gen/aidl/frameworks/base/core/java/android/hardware/hello/IHelloManager.aidl.d
./soong/.intermediates/frameworks/base/api/module-lib-api-stubs-docs-non-updatable/android_common/gen/aidl/frameworks/base/core/java/android/hardware/hello/IHelloManager.aidl.d
./soong/.intermediates/frameworks/base/api/api-stubs-docs-non-updatable/android_common/gen/aidl/frameworks/base/core/java/android/hardware/hello/IHelloManager.aidl.d
1
2
3
4
5
6
7
8
9
10
11

不同于之前的版本生成 java 源文件,这里生成的都是 class 文件,可以用你喜欢的反编译工具来查看具体的源码(我使用的是 vscode 的插件 Decompiler for Java):

接口的定义:

package .home.zzh0838.Project.aosp.android-14.0.0_r15.out.soong..intermediates.frameworks.base.framework-minus-apex.android_common.javac.shard38.classes.android.hardware.hello;

import android.os.IInterface;
import android.os.RemoteException;

public interface IHelloManager extends IInterface {
  public static final String DESCRIPTOR = "android.hardware.hello.IHelloManager";
  
  void hellohal_write(String paramString) throws RemoteException;
  
  String hellohal_read() throws RemoteException;
}
1
2
3
4
5
6
7
8
9
10
11
12

接口默认空实现:

package .home.zzh0838.Project.aosp.android-14.0.0_r15.out.soong..intermediates.frameworks.base.framework-minus-apex.android_common.javac.shard38.classes.android.hardware.hello;

import android.hardware.hello.IHelloManager;
import android.os.IBinder;
import android.os.RemoteException;

public class Default implements IHelloManager {
  public void hellohal_write(String str) throws RemoteException {}
  
  public String hellohal_read() throws RemoteException {
    return null;
  }
  
  public IBinder asBinder() {
    return null;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

服务端 Stub 类的实现:

package .home.zzh0838.Project.aosp.android-14.0.0_r15.out.soong..intermediates.frameworks.base.framework-minus-apex.android_common.javac.shard38.classes.android.hardware.hello;

import android.hardware.hello.IHelloManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import android.os.RemoteException;

public abstract class Stub extends Binder implements IHelloManager {
  static final int TRANSACTION_hellohal_write = 1;
  
  static final int TRANSACTION_hellohal_read = 2;
  
  public Stub() {
    attachInterface((IInterface)this, "android.hardware.hello.IHelloManager");
  }
  
  public static IHelloManager asInterface(IBinder obj) {
    if (obj == null)
      return null; 
    IInterface iin = obj.queryLocalInterface("android.hardware.hello.IHelloManager");
    if (iin != null && iin instanceof IHelloManager)
      return (IHelloManager)iin; 
    return (IHelloManager)new Proxy(obj);
  }
  
  public IBinder asBinder() {
    return (IBinder)this;
  }
  
  public static String getDefaultTransactionName(int transactionCode) {
    switch (transactionCode) {
      case 1:
        return "hellohal_write";
      case 2:
        return "hellohal_read";
    } 
    return null;
  }
  
  public String getTransactionName(int transactionCode) {
    this;
    return getDefaultTransactionName(transactionCode);
  }
  
  public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    String _arg0, _result, descriptor = "android.hardware.hello.IHelloManager";
    if (code >= 1 && code <= 16777215)
      data.enforceInterface(descriptor); 
    switch (code) {
      case 1598968902:
        reply.writeString(descriptor);
        return true;
    } 
    switch (code) {
      case 1:
        _arg0 = data.readString();
        data.enforceNoDataAvail();
        hellohal_write(_arg0);
        reply.writeNoException();
        return true;
      case 2:
        _result = hellohal_read();
        reply.writeNoException();
        reply.writeString(_result);
        return true;
    } 
    return super.onTransact(code, data, reply, flags);
  }
  
  public int getMaxTransactionId() {
    return 1;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

代理类 Proxy 的实现:

package .home.zzh0838.Project.aosp.android-14.0.0_r15.out.soong..intermediates.frameworks.base.framework-minus-apex.android_common.javac.shard38.classes.android.hardware.hello;

import android.hardware.hello.IHelloManager;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;

class Proxy implements IHelloManager {
  private IBinder mRemote;
  
  Proxy(IBinder remote) {
    this.mRemote = remote;
  }
  
  public IBinder asBinder() {
    return this.mRemote;
  }
  
  public String getInterfaceDescriptor() {
    return "android.hardware.hello.IHelloManager";
  }
  
  public void hellohal_write(String str) throws RemoteException {
    Parcel _data = Parcel.obtain(asBinder());
    Parcel _reply = Parcel.obtain();
    try {
      _data.writeInterfaceToken("android.hardware.hello.IHelloManager");
      _data.writeString(str);
      boolean _status = this.mRemote.transact(1, _data, _reply, 0);
      _reply.readException();
    } finally {
      _reply.recycle();
      _data.recycle();
    } 
  }
  
  public String hellohal_read() throws RemoteException {
    String _result;
    Parcel _data = Parcel.obtain(asBinder());
    Parcel _reply = Parcel.obtain();
    try {
      _data.writeInterfaceToken("android.hardware.hello.IHelloManager");
      boolean _status = this.mRemote.transact(2, _data, _reply, 0);
      _reply.readException();
      _result = _reply.readString();
    } finally {
      _reply.recycle();
      _data.recycle();
    } 
    return _result;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

基本就是 java binder 那一套东西,没什么特别要说的

# 硬件服务 Server 端实现

frameworks/base/services/core/java/com/android/server 目录下添加:

hello/
└── HelloService.java
1
2

其中 HelloService.java 的内容如下:

package com.android.server.hello;

import android.Manifest;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Context;
import android.hardware.hello.*;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.Trace;
import android.provider.Settings;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.server.SystemService;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.annotation.NonNull;
import android.hardware.hello.IHelloManager;
import android.hardware.hello.IHelloHal;


public class HelloService extends SystemService {

    // aidl hal 服务
    private IHelloHal mVintfHelloHal = null;
    // SystemServer 中的硬件服务
    private IHelloManager mHelloManager = null;

    private final class HelloManagerService extends IHelloManager.Stub { 
        
        @Override
        public void hellohal_write( @NonNull String str) throws android.os.RemoteException {
            try {
                if(mVintfHelloHal != null) {
                    mVintfHelloHal.hello_write(str);
                }
                
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        
        @Override
        public String hellohal_read() throws android.os.RemoteException {

            try {
                if(mVintfHelloHal != null) {
                    return mVintfHelloHal.hello_read();
                }
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }

            return "";
           
        }
    }

    public HelloService( Context context ) {
        super(context);
        IBinder binder = Binder.allowBlocking(
                        ServiceManager.waitForDeclaredService(IHelloHal.DESCRIPTOR + "/default"));
        if (binder != null) {
            mVintfHelloHal = IHelloHal.Stub.asInterface(binder);
        }

        mHelloManager = new HelloManagerService();

    }

    @Override
    public void onStart() {
        publishBinderService(Context.HELLO_SERVICE, (IBinder)mHelloManager);
    }

    @Override
    public void onBootPhase(int phase) {
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

接着在 SystemServer 中添加启动服务的代码:

    // 不要忘了导包
    import com.android.server.hello.HelloService;

    private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
        // ......
        t.traceBegin("StartHelloHalService");
        mSystemServiceManager.startService(HelloService.class);
        t.traceEnd();
        //......
    }
1
2
3
4
5
6
7
8
9
10

# 硬件服务客户端辅助代码实现

接着创建客户端的接口:

// frameworks/base/core/java/android/hardware/hello/HelloServiceManager.java
package android.hardware.hello;

import android.annotation.SystemService;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Singleton;
import android.os.ServiceManager;
import android.annotation.Nullable;

/**
 * { @hide }
 */
public final class HelloServiceManager {

    final Context mContext;

    /*
     * @hide
     */
    public HelloServiceManager (Context systemContext) {
        mContext = systemContext;
    }

    /**
     * @hide 只能系统调用
     */
    public static IHelloManager getServerice(){
        return I_HELLOHAL_MANAGER_SINGLETON.get();
    }

    //限制framework中的定义无法被外部应用访问
    @UnsupportedAppUsage
    private static final Singleton<IHelloManager> I_HELLOHAL_MANAGER_SINGLETON =
            new Singleton<IHelloManager>() {
                @Override
                protected IHelloManager create() {
                    final IBinder b= ServiceManager.getService(Context.HELLO_SERVICE);
                    final IHelloManager m = IHelloManager.Stub.asInterface(b);
                    return m;
                }
    };
    
    
    public void hellohal_write( @Nullable String str){
        try{
            getServerice().hellohal_write(str);
            return;
        }catch (RemoteException e){
            throw e.rethrowFromSystemServer();
        }
    }

    @Nullable
    public String hellohal_read() {
        try{
            return getServerice().hellohal_read();
        }catch (RemoteException e){
            throw e.rethrowFromSystemServer();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

接着修改 frameworks/base/core/java/android/app/SystemServiceRegistry.java

// 不要忘了 import 包
import android.hardware.hello.HelloHalManager;
import android.hardware.hello.SystemHelloHalManager;
static {
    //......
        registerService(Context.HELLO_SERVICE, HelloServiceManager.class,
            new CachedServiceFetcher<HelloServiceManager>() {
                @Override
                public HelloServiceManager createService(ContextImpl ctx)
                    throws ServiceNotFoundException {
                    return new HelloServiceManager();
                }});
    //......
    
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

接着编译:

source build/envsetup.sh
lunch aosp_cf_x86_64_phone-eng
make update-api
make framework-minus-apex -j32
1
2
3
4

# App 访问硬件服务

简单起见,这里我们直接在 Launcher 中加访问硬件服务的代码。

// packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

// 不要忘了导包
import android.hardware.hello.HelloServiceManager;
import android.content.Context;

    protected void onCreate(Bundle savedInstanceState) {

        HelloServiceManager manager = (HelloServiceManager) getSystemService(Context.HELLO_SERVICE);
        manager.hellohal_write("nihao");
    }
1
2
3
4
5
6
7
8
9
10
11

# Selinux 配置

system/sepolicy/prebuilts/api/34.0/private/service.tesystem/sepolicy/private/service.te 中添加:

type hello_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
1

system/sepolicy/prebuilts/api/34.0/private/service_contextssystem/sepolicy/private/service_contexts 中添加:

hello                                     u:object_r:hello_service:s0
1

system/sepolicy/prebuilts/api/34.0/private/system_app.tesystem/sepolicy/private/system_app.te

allow system_app hello_service:service_manager find;
1

# 编译运行

接着编译运行:

# 编译
source build/envsetup.sh
lunch aosp_cf_x86_64_phone-eng
make update-api
m
cvd start  -kernel_path=/home/zzh0838/Project/aosp/kernel/out/virtual_device_x86_64/dist/bzImage  -initramfs_path=/home/zzh0838/Project/aosp/kernel/out/virtual_device_x86_64/dist/initramfs.img
1
2
3
4
5
6

接着看 log:

adb logcat | grep hello

04-16 19:41:52.108     0     0 W         : drivers/char/hello_driver.c hello_init line 69
04-16 19:41:53.579     0     0 I init    : Parsing file /vendor/etc/init/android.hardware.hello.rc...
04-16 19:41:58.342     0     0 I init    : starting service 'vendor.hellohal-default'...
04-16 19:41:58.371     0     0 I init    : ... started service 'vendor.hellohal-default' has pid 339
04-16 19:41:58.440     0     0 I servicemanager: Found android.hardware.hello.IHelloHal/default in device VINTF manifest.
04-16 19:42:05.028   564   564 I SystemServiceManager: Starting com.android.server.hello.HelloService
04-16 19:42:05.075     0     0 I servicemanager: Found android.hardware.hello.IHelloHal/default in device VINTF manifest.
04-16 19:42:05.037   564   564 D SystemServerTiming: OnBootPhase_100_com.android.server.hello.HelloService
04-16 19:42:05.037   564   564 V SystemServerTiming: OnBootPhase_100_com.android.server.hello.HelloService took to complete: 0ms
04-16 19:42:07.167   564   564 D SystemServerTiming: OnBootPhase_200_com.android.server.hello.HelloService
04-16 19:42:07.167   564   564 V SystemServerTiming: OnBootPhase_200_com.android.server.hello.HelloService took to complete: 0ms
04-16 19:42:20.697   564   564 D SystemServerTiming: OnBootPhase_480_com.android.server.hello.HelloService
04-16 19:42:20.697   564   564 V SystemServerTiming: OnBootPhase_480_com.android.server.hello.HelloService took to complete: 0ms
04-16 19:42:20.748   564   564 D SystemServerTiming: OnBootPhase_500_com.android.server.hello.HelloService
04-16 19:42:20.748   564   564 V SystemServerTiming: OnBootPhase_500_com.android.server.hello.HelloService took to complete: 0ms
04-16 19:42:21.129   564   564 D SystemServerTiming: OnBootPhase_520_com.android.server.hello.HelloService
04-16 19:42:21.129   564   564 V SystemServerTiming: OnBootPhase_520_com.android.server.hello.HelloService took to complete: 0ms
04-16 19:42:21.211   564   564 D SystemServerTiming: OnBootPhase_550_com.android.server.hello.HelloService
04-16 19:42:21.211   564   564 V SystemServerTiming: OnBootPhase_550_com.android.server.hello.HelloService took to complete: 0ms
04-16 19:42:23.136   564   564 D SystemServerTiming: OnBootPhase_600_com.android.server.hello.HelloService
04-16 19:42:23.136   564   564 V SystemServerTiming: OnBootPhase_600_com.android.server.hello.HelloService took to complete: 0ms
04-16 19:42:23.255   564   564 D SystemServerTimingAsync: ssm.onStartUser-0_com.android.server.hello.HelloService
04-16 19:42:23.255   564   564 V SystemServerTimingAsync: ssm.onStartUser-0_com.android.server.hello.HelloService took to complete: 0ms
04-16 19:42:28.180   564   590 D ActivityManagerTiming: OnBootPhase_1000_com.android.server.hello.HelloService
04-16 19:42:28.180   564   590 V ActivityManagerTiming: OnBootPhase_1000_com.android.server.hello.HelloService took to complete: 0ms
04-16 19:42:28.473   564   597 D SystemServerTimingAsync: ssm.onUnlockingUser-0_com.android.server.hello.HelloService
04-16 19:42:28.473   564   597 V SystemServerTimingAsync: ssm.onUnlockingUser-0_com.android.server.hello.HelloService took to complete: 0ms
04-16 19:42:30.339     0     0 W         : drivers/char/hello_driver.c hello_drv_open line 44
04-16 19:42:30.339     0     0 W         : drivers/char/hello_driver.c hello_drv_write line 37
04-16 19:42:30.339     0     0 W         : drivers/char/hello_driver.c hello_drv_close line 50
04-16 19:42:31.222   564   597 D SystemServerTimingAsync: ssm.onUnlockedUser-0_com.android.server.hello.HelloService
04-16 19:42:31.222   564   597 V SystemServerTimingAsync: ssm.onUnlockedUser-0_com.android.server.hello.HelloService took to complete: 0ms
04-16 19:42:36.249   564  2605 D SystemServerTimingAsync: ssm.onCompletedEventUser-0_{|Unlocked|}_com.android.server.hello.HelloService
04-16 19:42:36.249   564  2605 V SystemServerTimingAsync: ssm.onCompletedEventUser-0_{|Unlocked|}_com.android.server.hello.HelloService took to complete: 0ms
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

从 Log 来看,成功调用到了 hello 驱动程序。

# 参考资料